/**
 * Copyright 2014-2020  the original author or authors.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.upb.webserver.org;

import cn.hutool.core.collection.CollectionUtil;
import com.upb.webserver.common.constant.Constant;
import com.upb.webserver.common.enums.PlatformEnum;
import com.upb.webserver.common.exception.WebServerException;
import com.upb.webserver.common.pojo.base.BasePageResponse;
import com.upb.webserver.common.pojo.org.RspOrgVO;
import com.upb.webserver.common.pojo.rest.fabric.data.BaseOrgInfo;
import com.upb.webserver.common.returncode.ConstantCode;
import com.upb.webserver.common.tools.JsonUtils;
import com.upb.webserver.common.tools.MybatisExampleTools;
import com.upb.webserver.common.tools.WebServerTools;
import com.upb.webserver.dao.entity.TbOrg;
import com.upb.webserver.dao.entity.TbOrgExample;
import com.upb.webserver.dao.mapper.TbCompanyMapper;
import com.upb.webserver.dao.mapper.TbDeveloperMapper;
import com.upb.webserver.dao.mapper.TbOrgMapper;
import com.upb.webserver.dao.mapper.TbWorkOrderMapper;
import com.upb.webserver.host.HostManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static com.upb.webserver.common.constant.Constant.FABRIC_ORG_DOMAIN_FORMAT;
import static com.upb.webserver.common.constant.Constant.FABRIC_ORG_MSP_FORMAT;

/**
 * services for account data.
 */
@Slf4j
@Service
public class OrgManager {
    @Autowired
    private TbOrgMapper orgMapper;
    @Autowired
    private TbWorkOrderMapper workOrderMapper;
    @Autowired
    private HostManager hostManager;
    @Autowired
    private TbCompanyMapper companyMapper;
    @Autowired
    private TbDeveloperMapper developerMapper;


    /**
     * @param example
     * @return
     */
    public BasePageResponse queryOrgByPage(TbOrgExample example) {
        log.info("start exec method [queryOrgByPage]. example:{}", JsonUtils.objToString(example));
        BasePageResponse pageResponse = BasePageResponse.initialize();
        pageResponse.setTotalCount(orgMapper.countByExample(example));
        if (pageResponse.getTotalCount() > 0) {
            example.setOrderByClause(Constant.ORDER_BY_GMT_MODIFIED_DESC);

            List<RspOrgVO> orgVOList = new ArrayList<>();
            List<TbOrg> tbOrgList = orgMapper.selectByExampleWithBLOBs(example);
            for (TbOrg tbOrg : tbOrgList) {
                RspOrgVO rspOrgVO = rspOrgVoFromTbOrg(tbOrg);
                orgVOList.add(rspOrgVO);
            }
            pageResponse.setData(orgVOList);
        }

        log.info("success exec method [queryOrgByPage]. result:{}", JsonUtils.objToString(pageResponse));
        return pageResponse;
    }

    /**
     * @param tbOrg
     * @return
     */
    private RspOrgVO rspOrgVoFromTbOrg(TbOrg tbOrg) {
        log.debug("start exec method [rspOrgVoFromTbOrg]. tbOrg:{}", JsonUtils.objToString(tbOrg));
        RspOrgVO rspOrgVO = new RspOrgVO();
        BeanUtils.copyProperties(tbOrg, rspOrgVO);
        //companyName
        try {
            rspOrgVO.setCompanyName(companyMapper.selectNameByPrimaryKey(tbOrg.getCompanyId()));

        } catch (Exception ex) {
            log.warn("fail get companyName", ex);
        }

        //developer
        try {
            rspOrgVO.setDeveloperAccount(developerMapper.selectByPrimaryKey(tbOrg.getDeveloperId()).getAccount());
        } catch (Exception ex) {
            log.warn("fail get developerAccount", ex);
        }
        log.debug("success exec method [rspOrgVoFromTbOrg]. rspOrgVO:{}", JsonUtils.objToString(rspOrgVO));
        return rspOrgVO;
    }


    /**
     * @param orgId
     * @return
     */
    public Integer getCompanyIdByOrgId(Integer orgId) {
        log.info("start exec method [getCompanyIdByOrgId]. orgId:{}", orgId);

        TbOrg tbOrg = orgMapper.selectByPrimaryKey(orgId);
        if (null == tbOrg) {
            log.info("start exec method [getCompanyIdByOrgId]. not found record by orgId:{}", orgId);
            throw new WebServerException(ConstantCode.INVALID_ORG_ID);
        }
        return tbOrg.getCompanyId();
    }

    /**
     * @param companyId
     * @return
     */
    public List<TbOrg> listOrgByCompanyId(Integer companyId) {
        log.info("start exec method [listOrgByCompanyId]. companyId:{}", companyId);
        TbOrgExample example = MybatisExampleTools.initSampleExample(TbOrgExample.class, new TbOrg(companyId));
        List<TbOrg> orgList = orgMapper.selectByExample(example);
        log.info("success exec method [listOrgByCompanyId]. result:{}", JsonUtils.objToString(orgList));
        return orgList;
    }

    /**
     * @param companyIdList
     * @return
     */
    public List<TbOrg> queryOrgByCompanyIdList(List<Integer> companyIdList) {
        log.info("start exec method [listOrgByCompanyId]. companyIdList:{}", JsonUtils.objToString(companyIdList));
        if (CollectionUtil.isEmpty(companyIdList))
            return Collections.EMPTY_LIST;

        TbOrgExample example = new TbOrgExample();
        TbOrgExample.Criteria criteria = example.createCriteria();
        criteria.andCompanyIdIn(companyIdList);

        List<TbOrg> orgList = orgMapper.selectByExample(example);
        log.info("success exec method [listOrgByCompanyId]. result:{}", JsonUtils.objToString(orgList));
        return orgList;
    }


    /**
     * @param orgId
     * @return
     */
    public TbOrg verifyOrgId(int orgId) {
        log.info("start exec method [verifyOrgId]. orgId:{}", orgId);
        TbOrg tbOrg = orgMapper.selectByPrimaryKey(orgId);
        if (null == tbOrg) {
            log.warn("fail exec method [verifyOrgId]. not found record by orgId{}", orgId);
            throw new WebServerException(ConstantCode.INVALID_ORG_ID);
        }
        log.info("success exec method [verifyOrgId]. result:{}", JsonUtils.objToString(tbOrg));
        return tbOrg;
    }


    /**
     * @param orgId
     * @return
     */
    public RspOrgVO queryOrgDetail(Integer orgId) {
        log.info("start exec method [queryOrgDetail]. orgId:{}", orgId);
        TbOrg tbOrg = orgMapper.selectByPrimaryKey(orgId);
        if (null == tbOrg) return null;
        RspOrgVO rspOrgVO = new RspOrgVO();
        BeanUtils.copyProperties(tbOrg, rspOrgVO);
        log.info("start exec method [queryOrgDetail]. result:{}", JsonUtils.objToString(rspOrgVO));
        return rspOrgVO;
    }


    /**
     * @param orgId
     * @return
     */
    public BaseOrgInfo.OrgTag orgTagFromOrgId(int orgId) {
        log.debug("start exec method [orgTagFromOrgId]. orgId:{}", orgId);
        TbOrg tbOrg = verifyOrgId(orgId);

        BaseOrgInfo.OrgTag orgTag = new BaseOrgInfo.OrgTag();
        orgTag.setMspId(String.format(FABRIC_ORG_MSP_FORMAT, WebServerTools.upperCaseFirstChar(tbOrg.getName())));
        orgTag.setDomain(String.format(FABRIC_ORG_DOMAIN_FORMAT, tbOrg.getName(), tbOrg.getSuffix()));
        log.debug("success exec method [orgTagFromOrgId]. result:{}", JsonUtils.objToString(orgTag));
        return orgTag;
    }

    /**
     * @param orgId
     * @return
     */
    public String getAffiliationByOrgId(int orgId) {
        log.info("start exec method [getAffiliationByOrgId]. orgId:{}", orgId);
        TbOrg tbOrg = verifyOrgId(orgId);
        String orgDomain = String.format(FABRIC_ORG_DOMAIN_FORMAT, tbOrg.getName(), tbOrg.getSuffix());
        String[] tempArr = orgDomain.split("\\.");

        StringBuffer affiliationBuffer = new StringBuffer();
        for (int i = tempArr.length - 1; i >= 0; i--) {
            affiliationBuffer.append(tempArr[i]);
            if (i > 0) {
                affiliationBuffer.append(".");
            }
        }

        String affiliation = affiliationBuffer.toString();
        log.info("start exec method [getAffiliationByOrgId]. result:{}", affiliation);
        return affiliation;
    }


    /**
     * @param platform
     * @param creatorAccountId
     * @return
     */
    public long countOrgByCreator(PlatformEnum platform, int creatorAccountId) {
        log.debug("start exec method [countOrgByCreator]. platform:{} creatorAccountId:{}", platform, creatorAccountId);
        TbOrgExample example = MybatisExampleTools.initSampleExample(TbOrgExample.class, new TbOrg(platform, creatorAccountId));
        long count = orgMapper.countByExample(example);
        log.debug("success exec method [countOrgByCreator]. platform:{} creatorAccountId:{} count:{}", platform, creatorAccountId, count);
        return count;
    }
}
